package com.hn.springframework.aop;

import com.hn.springframework.aop.intercept.HNMethodInvocation;
import com.hn.springframework.aop.support.HNAdvisedSupport;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

public class HNJdkDynamicAopProxy implements HNAopProxy, InvocationHandler {

    private HNAdvisedSupport advised;

    public HNJdkDynamicAopProxy(HNAdvisedSupport advised) {
        this.advised = advised;
    }

    @Override
    public Object getProxy() {
        return getProxy(this.advised.getTargetClass().getClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        return Proxy.newProxyInstance(classLoader, this.advised.getTargetClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object retVal = null;
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, this.advised.getTargetClass());
        if (chain.isEmpty()) {
            retVal = method.invoke(this.advised.getTarget(), args);
        } else {
            HNMethodInvocation invocation = new HNMethodInvocation(proxy, this.advised.getTarget(), method, args, this.advised.getTargetClass(), chain);
            retVal = invocation.proceed();
        }
        return retVal;
    }
}
